package biback.domain.common

import cats.Monad
import biback.domain._
import biback.domain.common.model.{Branch, BranchLevel, ChannelType, Teller}
import biback.utils._

trait BranchAlgebra[F[_]] {
  val branch: BranchAlgebra.Service[F]
}

object BranchAlgebra {

  trait Service[F[_]] extends GeneralAlgebra[F] {
    def get(no: BranchNo)(implicit F: Monad[F]): ErrOrF[Option[Branch]] =
      orF(Left(MethodNoImplement("get")))

    def getTeller(no: TellerNo)(implicit F: Monad[F]): ErrOrF[Option[Teller]] =
      orF(Left(MethodNoImplement("getTeller")))

    def getBranchNo(channel: ChannelType)(implicit F: Monad[F]): ErrOrF[Option[BranchNo]] =
      orF(Left(MethodNoImplement("getBranchNo")))

    def getHeadBranch()(implicit F: Monad[F]): ErrOrF[Option[Branch]] =
      orF(Left(MethodNoImplement("getHeadBranch")))

    def foundHeadBranch()(implicit F: Monad[F]): ErrOrF[Branch] =
      foundF(getHeadBranch, HeadBranchNotFound)

    def notFoundHeadBranch()(implicit F: Monad[F]): ErrOrNoneF =
      notFoundF(getHeadBranch, HeadBranchFound)

    def getBranches(nos: Set[BranchNo])(implicit F: Monad[F]): ErrOrF[List[Branch]] =
      orF(Left(MethodNoImplement("getBranches")))

    def found(no: BranchNo)(implicit F: Monad[F]): ErrOrF[Branch] =
      foundF(get(no), BranchNotFound(no))

    def notFound(no: BranchNo)(implicit F: Monad[F]): ErrOrNoneF =
      notFoundF(get(no), BranchFound(no))

    def foundTeller(no: TellerNo)(implicit F: Monad[F]): ErrOrF[Teller] =
      foundF(getTeller(no), TellerNotFound(no))

    def foundBranchNo(channel: ChannelType)(implicit F: Monad[F]): ErrOrF[BranchNo] =
      foundF(getBranchNo(channel), ChannelNoFound(channel))

    def createTlrNo()(implicit F: Monad[F]): ErrOrF[TellerNo] =
      orF(Left(MethodNoImplement("createTlrNo")))

    def create(brcNo: BranchNo, ctx: TrnContext, level: BranchLevel, upBrcNo: Option[BranchNo] = None)(implicit F: Monad[F]): ErrOrNoneF =
      orF(Left(MethodNoImplement("create")))

    def addTeller(brcNo: BranchNo, ctx: TrnContext, tlrNo: TellerNo)(implicit F: Monad[F]): ErrOrNoneF =
      orF(Left(MethodNoImplement("addTeller")))
  }

}
